package com.xyht.sca_s.student_manage_system.modules.bigData.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.bigData.entity.resp.*;
import com.xyht.sca_s.student_manage_system.modules.bigData.service.SmsEnrolStudentInfoService;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.entity.SmsEnrolStudent;
import com.xyht.sca_s.student_manage_system.modules.enrolStudent.mapper.SmsEnrolStudentMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.bigData.constant.EnrolStudentSexConstant.SEX_BOY;
import static com.xyht.sca_s.student_manage_system.modules.bigData.constant.EnrolStudentSexConstant.SEX_GIRL;

/**
 * <p>
 * 招生信息
 * </p>
 *
 * @author XYHT
 * @since 2023-08-31
 */
@Service
public class SmsEnrolStudentInfoServiceImpl implements SmsEnrolStudentInfoService {

    @Resource
    private SmsEnrolStudentMapper smsEnrolStudentMapper;

    @Override
    public ResponseResult getEnrolStudent(String thisYear) {
        if(isNullOrEmpty(thisYear)){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        int yearInt = Integer.parseInt(thisYear);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, yearInt);
        calendar.set(Calendar.MONTH,11);
        Date endDate = TimeUtil.GetEndDateOfMonth(calendar.getTime());
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.set(Calendar.YEAR, yearInt-1);
        startCalendar.set(Calendar.MONTH,12);
        Date startDate =  TimeUtil.GetStartDateOfMonth(startCalendar.getTime());

        SmsEnrolStudentInfoResp smsEnrolStudentResp = new SmsEnrolStudentInfoResp();
        //招生列表
        List<SmsEnrolStudentListResp> studentList = new ArrayList<>();
        studentList = smsEnrolStudentMapper.selectList(new LambdaQueryWrapper<SmsEnrolStudent>()
                .ge(SmsEnrolStudent::getCreateTime,startDate)
                .le(SmsEnrolStudent::getCreateTime,endDate)
                .orderByDesc(SmsEnrolStudent::getCreateTime))
                .stream()
                .map(smsEnrolStudent -> {
                    SmsEnrolStudentListResp studentListResp = new SmsEnrolStudentListResp();
                    BeanUtils.copyProperties(smsEnrolStudent, studentListResp);
                    return studentListResp;
                })
                .collect(Collectors.toList());
        smsEnrolStudentResp.setEnrolStudentList(studentList);

        //生源分布
        List<SmsEnrolStudentOriginResp> studentOriginList = new ArrayList<>();
        List<Map<String, Object>> maps = smsEnrolStudentMapper.selectMaps(new QueryWrapper<SmsEnrolStudent>()
                .select("count(*) as originSum,origin")
                .lambda()
                .ge(SmsEnrolStudent::getCreateTime,startDate)
                .le(SmsEnrolStudent::getCreateTime,endDate)
                .groupBy(SmsEnrolStudent::getOrigin));
        if(maps != null && maps.size() > 0){
            for (Map<String, Object> map : maps) {
                SmsEnrolStudentOriginResp studentOriginResp = JSONObject.parseObject(JSON.toJSONString(map), SmsEnrolStudentOriginResp.class);
                if(!isNullOrEmpty(studentOriginResp)){
                    SmsEnrolStudentOriginResp studentOrigin = new SmsEnrolStudentOriginResp();
                    studentOrigin.setOrigin(studentOriginResp.getOrigin());
                    studentOrigin.setOriginSum(studentOriginResp.getOriginSum());
                    studentOriginList.add(studentOrigin);
                }
            }
        }
        smsEnrolStudentResp.setOriginDistribution(studentOriginList);

        //男女占比
        SmsEnrolStudentBoyOrGirlRatioResp boyOrGirlRatioResp = new SmsEnrolStudentBoyOrGirlRatioResp();
        int boySum = 0;
        int girlSum = 0;
        List<Map<String, Object>> sexMaps = smsEnrolStudentMapper.selectMaps(new QueryWrapper<SmsEnrolStudent>()
                .select("count(*) as sum,sex")
                .lambda()
                .ge(SmsEnrolStudent::getCreateTime,startDate)
                .le(SmsEnrolStudent::getCreateTime,endDate)
                .groupBy(SmsEnrolStudent::getSex));
        if(sexMaps != null && sexMaps.size() > 0){
            for (Map<String, Object> map : sexMaps) {
                SmsEnrolStudentSumAndSexResp sumAndSexResp = JSONObject.parseObject(JSON.toJSONString(map), SmsEnrolStudentSumAndSexResp.class);
                if(!isNullOrEmpty(sumAndSexResp)){
                    Integer sex = sumAndSexResp.getSex();
                    Integer sum = sumAndSexResp.getSum();
                    if(sex == SEX_BOY){
                        boySum = sum;
                        boyOrGirlRatioResp.setBoySum(boySum);
                    }else if(sex == SEX_GIRL){
                        girlSum = sum;
                        boyOrGirlRatioResp.setGirlSum(girlSum);
                    }
                }
            }
        }else {
            boyOrGirlRatioResp.setBoySum(boySum);
            boyOrGirlRatioResp.setGirlSum(girlSum);
        }
        int sum = boySum + girlSum;
        if(sum == 0){
            boyOrGirlRatioResp.setBoyRatio(0);
            boyOrGirlRatioResp.setGirlRatio(0);
        }else {
            double boyRatio = Math.ceil((double) boySum / sum * 100);
            double girlRatio = Math.floor((double) girlSum / sum * 100);
            boyOrGirlRatioResp.setBoyRatio((int)boyRatio);
            boyOrGirlRatioResp.setGirlRatio((int)girlRatio);
        }
        smsEnrolStudentResp.setBoyOrGirlRatio(boyOrGirlRatioResp);

        //各年龄总数
        List<SmsEnrolStudentAgeResp> smsEnrolStudentAgeList = new ArrayList<>();
        List<Map<String, Object>> ageMaps = smsEnrolStudentMapper.selectMaps(new QueryWrapper<SmsEnrolStudent>()
                .select("SUM(CASE WHEN sex = 0 THEN 1 ELSE 0 END) girlSum,SUM(CASE WHEN sex = 1 THEN 1 ELSE 0 END) boySum,birth_year as birthYear")
                .lambda()
                .orderByDesc(SmsEnrolStudent::getBirthYear)
                .groupBy(SmsEnrolStudent::getBirthYear));
        if(ageMaps != null && ageMaps.size() > 0){
            for (Map<String, Object> ageMap : ageMaps) {
                SmsSumAndBirthYearResp smsSumAndBirthYearResp = JSONObject.parseObject(JSON.toJSONString(ageMap), SmsSumAndBirthYearResp.class);
                if(!isNullOrEmpty(smsSumAndBirthYearResp)){
                    SmsEnrolStudentAgeResp smsEnrolStudentAgeResp = new SmsEnrolStudentAgeResp();
                    smsEnrolStudentAgeResp.setGirlSum(smsSumAndBirthYearResp.getGirlSum());
                    smsEnrolStudentAgeResp.setBoySum(smsSumAndBirthYearResp.getBoySum());
                    Integer birthYear = smsSumAndBirthYearResp.getBirthYear();
                    //获取年龄
                    int age = Integer.parseInt(thisYear) - birthYear;
                    smsEnrolStudentAgeResp.setAge(age);
                    smsEnrolStudentAgeList.add(smsEnrolStudentAgeResp);
                }
            }
        }

        smsEnrolStudentResp.setAgeDistribution(smsEnrolStudentAgeList);

        return CommonResult.success(smsEnrolStudentResp);
    }

    @Override
    public ResponseResult getNationDistribution() {
        List<SmsEnrolNationResp> enrolNationList = new ArrayList<>();
        QueryWrapper<SmsEnrolStudent> enrolStudentQueryWrapper = new QueryWrapper<>();
        enrolStudentQueryWrapper.
                select("count(*) as nationSum,nation")
                .lambda()
                .groupBy(SmsEnrolStudent::getNation);
        List<Map<String, Object>> maps = smsEnrolStudentMapper.selectMaps(enrolStudentQueryWrapper);
        Integer sum = smsEnrolStudentMapper.selectCount(null);
        int otherSum = 0;
        if (maps != null && maps.size() > 0) {
            for (int i = 0; i < maps.size(); i++) {
                SmsEnrolNationResp smsEnrolNationResp = new SmsEnrolNationResp();
                SmsEnrolNationResp smsEnrolNation = JSONObject.parseObject(JSON.toJSONString(maps.get(i)), SmsEnrolNationResp.class);
                if (!isNullOrEmpty(smsEnrolNation)) {
                    smsEnrolNationResp.setNationSum(smsEnrolNation.getNationSum());
                    //后五条数据用其他代表
                    if (i > 5) {
                        smsEnrolNationResp.setNation("其他");
                        smsEnrolNationResp.setNationRatio(100 - otherSum);
                        break;
                    }else {
                        smsEnrolNationResp.setNation(smsEnrolNation.getNation());
                        double ration = (double) smsEnrolNation.getNationSum() / sum * 100;
                        if(i == maps.size() - 1) {
                            smsEnrolNationResp.setNationRatio(100 - otherSum);
                        }else {
                            smsEnrolNationResp.setNationRatio((int) ration);
                        }
                        otherSum += (int) ration;
                    }
                    enrolNationList.add(smsEnrolNationResp);
                }
            }
        }
        return CommonResult.success(enrolNationList);
    }

    @Override
    public ResponseResult getBirthDistribution() {
        List<SmsEnrolBirthResp> enrolBirthList = new ArrayList<>();
        QueryWrapper<SmsEnrolStudent> enrolStudentQueryWrapper = new QueryWrapper<>();
        enrolStudentQueryWrapper.
                select("count(*) as birthYearSum,birth_year as birthYear")
                .lambda()
                .groupBy(SmsEnrolStudent::getBirthYear)
                .orderByDesc(SmsEnrolStudent::getBirthYear);
        List<Map<String, Object>> maps = smsEnrolStudentMapper.selectMaps(enrolStudentQueryWrapper);
        if(maps != null && maps.size() > 0){
            for (Map<String, Object> map : maps) {
                SmsEnrolBirthResp smsEnrolBirthResp = new SmsEnrolBirthResp();
                SmsEnrolBirthResp birthResp = JSONObject.parseObject(JSON.toJSONString(map), SmsEnrolBirthResp.class);
                if(!isNullOrEmpty(birthResp)){
                    smsEnrolBirthResp.setBirthYear(birthResp.getBirthYear());//出生年份
                    smsEnrolBirthResp.setBirthYearSum(birthResp.getBirthYearSum());
                    enrolBirthList.add(smsEnrolBirthResp);
                }
            }
        }
        return CommonResult.success(enrolBirthList);
    }

    @Override
    public ResponseResult getCollegeBoyAndGirlRation() {
        List<SmsEnrolCollegeRationResp> enrolCollegeRationList = new ArrayList<>();
        QueryWrapper<SmsEnrolStudent> enrolStudentQueryWrapper = new QueryWrapper<>();
        //查询各院系男女生数
        enrolStudentQueryWrapper.
                select("SUM(CASE WHEN sex = 0 THEN 1 ELSE 0 END) girlSum,SUM(CASE WHEN sex = 1 THEN 1 ELSE 0 END) boySum,college")
                .lambda()
                .groupBy(SmsEnrolStudent::getCollege);

        List<Map<String, Object>> maps = smsEnrolStudentMapper.selectMaps(enrolStudentQueryWrapper);
        if (maps != null && maps.size() > 0) {
            for (Map<String, Object> map : maps) {
                SmsEnrolCollegeRationResp enrolCollegeRationResp = new SmsEnrolCollegeRationResp();
                SmsEnrolCollegeRationResp collegeRationResp = JSONObject.parseObject(JSON.toJSONString(map), SmsEnrolCollegeRationResp.class);
                if (!isNullOrEmpty(collegeRationResp)) {
                    enrolCollegeRationResp.setCollege(collegeRationResp.getCollege());//院系
                    enrolCollegeRationResp.setBoySum(collegeRationResp.getBoySum());
                    enrolCollegeRationResp.setGirlSum(collegeRationResp.getGirlSum());
                    int sum = collegeRationResp.getBoySum() + collegeRationResp.getGirlSum();
                    if (sum == 0) {
                        enrolCollegeRationResp.setBoySumRation(0);
                        enrolCollegeRationResp.setGirlSumRation(0);
                    } else {
                        double boyRatio = Math.ceil((double) collegeRationResp.getBoySum() / sum * 100);
                        double girlRatio = Math.floor((double) collegeRationResp.getGirlSum() / sum * 100);
                        enrolCollegeRationResp.setBoySumRation((int) boyRatio);
                        enrolCollegeRationResp.setGirlSumRation((int) girlRatio);
                    }
                    enrolCollegeRationList.add(enrolCollegeRationResp);
                }
            }
        }
        return CommonResult.success(enrolCollegeRationList);
    }

    @Override
    public ResponseResult getBoyAndGirlSum(String beginTimeStr, String endTimeStr) {
        List<SmsEnrolBoyAndGirlResp> enrolBoyAndGirlList = new ArrayList<>();
        if(isNullOrEmpty(beginTimeStr,endTimeStr)){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        int beginInt = Integer.parseInt(beginTimeStr);
        int endInt = Integer.parseInt(endTimeStr);
        if(beginInt > endInt){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //循环年份 填加数据
        while (beginInt <= endInt) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.YEAR, beginInt);
            calendar.set(Calendar.MONTH, 11);
            Date endDate = TimeUtil.GetEndDateOfMonth(calendar.getTime());
            Calendar calendar1 = Calendar.getInstance();
            calendar1.set(Calendar.YEAR, beginInt-1);
            calendar1.set(Calendar.MONTH, 12);
            Date startDate = TimeUtil.GetStartDateOfMonth(calendar1.getTime());
            //查询某一年 男女生总数
            List<Map<String, Object>> ageMaps = smsEnrolStudentMapper.selectMaps(new QueryWrapper<SmsEnrolStudent>()
                    .select("SUM(CASE WHEN sex = 0 THEN 1 ELSE 0 END) girlSum,SUM(CASE WHEN sex = 1 THEN 1 ELSE 0 END) boySum")
                    .lambda()
                    .ge(SmsEnrolStudent::getCreateTime,startDate)
                    .le(SmsEnrolStudent::getCreateTime,endDate)
                    .orderByAsc(SmsEnrolStudent::getCreateTime));
            if(ageMaps != null && ageMaps.size() > 0){
                for (Map<String, Object> ageMap : ageMaps) {
                    SmsSumAndBirthYearResp smsSumAndBirthYearResp = JSONObject.parseObject(JSON.toJSONString(ageMap), SmsSumAndBirthYearResp.class);
                    if(!isNullOrEmpty(smsSumAndBirthYearResp)){
                        Integer girlSum = smsSumAndBirthYearResp.getGirlSum();
                        Integer boySum = smsSumAndBirthYearResp.getBoySum();
                        SmsEnrolBoyAndGirlResp enrolBoyAndGirlResp = new SmsEnrolBoyAndGirlResp();
                        enrolBoyAndGirlResp.setGirlSum(girlSum);
                        enrolBoyAndGirlResp.setBoySum(boySum);
                        enrolBoyAndGirlResp.setThisYear(beginInt);
                        enrolBoyAndGirlResp.setSum(girlSum + boySum);
                        enrolBoyAndGirlList.add(enrolBoyAndGirlResp);
                    }
                }
            }else {
                SmsEnrolBoyAndGirlResp enrolBoyAndGirlResp = new SmsEnrolBoyAndGirlResp();
                enrolBoyAndGirlResp.setGirlSum(0);
                enrolBoyAndGirlResp.setBoySum(0);
                enrolBoyAndGirlResp.setThisYear(beginInt);
                enrolBoyAndGirlResp.setSum(0);
                enrolBoyAndGirlList.add(enrolBoyAndGirlResp);
            }
            beginInt ++;
        }
        return CommonResult.success(enrolBoyAndGirlList);
    }

}
